package csc411;

import java.util.ArrayList;
import java.util.Iterator;

//	Accounts Manager manages the accounts list in the server
public class AccountsManager {


	// list of accounts
	private ArrayList accounts;

	// keeps track of last account num
	private int lastAccountNum;

	public AccountsManager() {

		this.accounts = new ArrayList();
		this.lastAccountNum = 0;

		this.initAccounts();

	}

	// create initial accounts in the 'database'
	private void initAccounts() {

		this.addNewAccount("John", "1234", Currency.USD, 100.10f);

		this.addNewAccount("Sally", "5678", Currency.USD, 200.20f);

		this.addNewAccount("Margot", "9876", Currency.SGD, 300.30f);

		this.addNewAccount("Davendra", "5432", Currency.SGD, 400.40f);

		this.addNewAccount("Ali", "1023", Currency.SGD, 500.50f);

		//System.out.println("Created (" + this.accounts.size() + ") initial accounts");

		//this.printAllAccounts();

	}

	public void printAllAccounts() {
		Iterator itr = this.accounts.iterator();

		Account temp;

		while (itr.hasNext()) {
			temp = (Account) itr.next();

			System.out.println("#:" + temp.getAccountNum());
			System.out.println("Name:" + temp.getName());
			System.out.println("Password:" + temp.getPassword());
			System.out.println("Type:" + temp.getType());
			System.out.println("Balance:" + temp.getBalance());
			System.out.println();
		}
	}

	private int getNewAccountNum() {
		int newAccountNum = this.lastAccountNum;

		this.lastAccountNum++;

		return newAccountNum;

	}

	public int getNumofAccounts() {
		return this.accounts.size();
	}

	// adds new account into the accounts list
	// returns Account object
	public Account addNewAccount(
			String name, String password, Currency type, float initAmount) {

		// account id is its index in the accounts list
		int newAccountNum = this.getNewAccountNum();

		Account newAccount =
				new Account(newAccountNum, name, password, type, initAmount);

		this.accounts.add(newAccount);

		return newAccount;
	}


	// gets the account object with the given id, name and password
	// it checks that all given info are correct, otherwise throws exception
	// return account object
	public Account getAccount(
			int accountNum, String name, String password) throws Exception {

		Account account = null;

		// try to get the account by iterating thru the accounts list
		for (int i = 0; i < this.accounts.size(); i++) {
			if (((Account) this.accounts.get(i)).getAccountNum() == accountNum) {
				account = (Account) this.accounts.get(i);
				break;
			}

		}

		if (account == null) {
			throw new Exception("Account ("+ accountNum +") does not exist");
		}

		if (!name.equals(account.getName())) {
			throw new Exception("Invalid account information");
		}

		if (!password.equals(account.getPassword())) {
			throw new Exception("Invalid account information");
		}

		// if account exists and valid info was given, return account obj

		return account;

	}

        // gets the account object with the given id, name and password
	// it checks that all given info are correct, otherwise throws exception
	// return account object
	public Account getAccountTransfer(int accountNum) throws Exception {
        // Nadiah (230310:1230)
		Account account = null;

		// try to get the account by iterating thru the accounts list
		for (int i = 0; i < this.accounts.size(); i++) {
			if (((Account) this.accounts.get(i)).getAccountNum() == accountNum) {
				account = (Account) this.accounts.get(i);
				break;
			}

		}

		if (account == null) {
			throw new Exception("Account ("+accountNum+") does not exist");
		}

		// if account exists and valid info was given, return account obj

		return account;

	}

	// removes account with given id, name, password
	// throws exception if given info are incorrect
	// return Account object that was just deleted if successful
	public Account removeAccount(int accountNum, String name, String password)
			throws Exception {

		// try to get the account with the provided info
		// if the acct info is incorrect, will propagate the exception upwards
		Account account = this.getAccount(accountNum, name, password);

		this.accounts.remove(account);

		return account;
	}

	// deposits an amount into an account of given id, name, password
	// throws exception if given info are incorrect
	// return the Account object
	public Account deposit(int accountNum, String name, String password,
			Currency type, float amount) throws Exception {

		// try to get the account with the provided info
		// if the acct info is incorrect, will propagate the exception upwards
		Account account = this.getAccount(accountNum, name, password);

		account.deposit(type, amount);

		return account;

	}

        // deposits an amount into an account of given id, name, password
	// throws exception if given info are incorrect
	// return the Account object
	public Account depositTransfer(int accountNum, Currency type, float amount) throws Exception {
        // Nadiah (230310:1020)
            
		Account account = this.getAccountTransfer(accountNum);

		account.deposit(type, amount);

		return account;

	}

	// withdraws an amount into an account of given id, name, password
	// throws exception if given info are incorrect
	// return the Account object
	public Account withdraw(int accountNum, String name, String password,
			Currency type, float amount) throws Exception {

		// note: amount is a negative value

		// try to get the account with the provided info
		// if the acct info is incorrect, will propagate the exception upwards
		Account account = this.getAccount(accountNum, name, password);

		account.withdraw(type, amount);

		return account;

	}
}

